home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / lang / Python16_Src.lha / Python16_Source / Modules / mmapmodule.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-04  |  18.7 KB  |  870 lines

  1. /*
  2.  /  Author: Sam Rushing <rushing@nightmare.com>
  3.  /  Hacked for Unix by A.M. Kuchling <amk1@bigfoot.com> 
  4.  /  $Id: mmapmodule.c,v 2.8 2000/05/03 23:44:32 guido Exp $
  5.  
  6.  / mmapmodule.cpp -- map a view of a file into memory
  7.  /
  8.  / todo: need permission flags, perhaps a 'chsize' analog
  9.  /   not all functions check range yet!!!
  10.  /
  11.  /
  12.  / Note: This module currently only deals with 32-bit file
  13.  /   sizes.
  14.  /
  15.  / The latest version of mmapfile is maintained by Sam at
  16.  / ftp://squirl.nightmare.com/pub/python/python-ext.
  17. */
  18.  
  19. #include <Python.h>
  20.  
  21. #ifndef MS_WIN32
  22. #define UNIX
  23. #endif
  24.  
  25. #ifdef MS_WIN32
  26. #include <windows.h>
  27. #endif
  28.  
  29. #ifdef UNIX
  30. #include <unistd.h>
  31. #include <sys/mman.h>
  32. #endif
  33.  
  34. #include <string.h>
  35. #include <sys/types.h>
  36.  
  37. static PyObject *mmap_module_error;
  38.  
  39. typedef struct {
  40.     PyObject_HEAD
  41.     char *    data;
  42.     size_t    size;
  43.     size_t    pos;
  44.  
  45. #ifdef MS_WIN32
  46.     HANDLE    map_handle;
  47.     HFILE    file_handle;
  48.     char *    tagname;
  49. #endif
  50.  
  51. #ifdef UNIX
  52.   /* No Unix-specific information at this point in time */
  53. #endif
  54. } mmap_object;
  55.  
  56. static void
  57. mmap_object_dealloc(mmap_object * m_obj)
  58. {
  59. #ifdef MS_WIN32
  60.     UnmapViewOfFile (m_obj->data);
  61.     CloseHandle (m_obj->map_handle);
  62.     CloseHandle ((HANDLE)m_obj->file_handle);
  63. #endif /* MS_WIN32 */
  64.  
  65. #ifdef UNIX
  66.     if (m_obj->data!=NULL) {
  67.         msync(m_obj->data, m_obj->size, MS_SYNC | MS_INVALIDATE);
  68.         munmap(m_obj->data, m_obj->size);
  69.     }
  70. #endif /* UNIX */
  71.  
  72.     PyObject_Del(m_obj);
  73. }
  74.  
  75. static PyObject *
  76. mmap_close_method (mmap_object * self, PyObject * args)
  77. {
  78. #ifdef MS_WIN32
  79.     UnmapViewOfFile (self->data);
  80.     CloseHandle (self->map_handle);
  81.     CloseHandle ((HANDLE)self->file_handle);
  82.     self->map_handle = (HANDLE) NULL;
  83. #endif /* MS_WIN32 */
  84.  
  85. #ifdef UNIX
  86.     munmap(self->data, self->size);
  87.     self->data = NULL;
  88. #endif
  89.  
  90.     Py_INCREF (Py_None);
  91.     return (Py_None);
  92. }
  93.  
  94. #ifdef MS_WIN32
  95. #define CHECK_VALID(err)                        \
  96. do {                                    \
  97.     if (!self->map_handle) {                        \
  98.     PyErr_SetString (PyExc_ValueError, "mmap closed or invalid");    \
  99.     return err;                            \
  100.     }                                    \
  101. } while (0)
  102. #endif /* MS_WIN32 */
  103.  
  104. #ifdef UNIX
  105. #define CHECK_VALID(err)                        \
  106. do {                                    \
  107.     if (self->data == NULL) {                        \
  108.     PyErr_SetString (PyExc_ValueError, "mmap closed or invalid");    \
  109.     return err;                            \
  110.     }                                \
  111. } while (0)
  112. #endif /* UNIX */
  113.  
  114. static PyObject *
  115. mmap_read_byte_method (mmap_object * self,
  116.                PyObject * args)
  117. {
  118.     char value;
  119.     char * where;
  120.     CHECK_VALID(NULL);
  121.     if (self->pos >= 0 && self->pos < self->size) {
  122.             where = self->data + self->pos;
  123.         value = (char) *(where);
  124.         self->pos += 1;
  125.         return Py_BuildValue("c", (char) *(where));
  126.     } else {
  127.         PyErr_SetString (PyExc_ValueError, "read byte out of range");
  128.         return NULL;
  129.     }
  130. }
  131.  
  132. static PyObject *
  133. mmap_read_line_method (mmap_object * self,
  134.                PyObject * args)
  135. {
  136.     char * start = self->data+self->pos;
  137.     char * eof = self->data+self->size;
  138.     char * eol;
  139.     PyObject * result;
  140.  
  141.     CHECK_VALID(NULL);
  142.  
  143.     eol = memchr(start, '\n', self->size - self->pos);
  144.     if (!eol)
  145.         eol = eof;
  146.     else
  147.         ++eol;        /* we're interested in the position after the
  148.                    newline. */
  149.     result = PyString_FromStringAndSize(start, (long) (eol - start));
  150.     self->pos += (eol - start);
  151.     return (result);
  152. }
  153.  
  154. static PyObject *
  155. mmap_read_method (mmap_object * self,
  156.               PyObject * args)
  157. {
  158.     long num_bytes;
  159.     PyObject *result;
  160.  
  161.     CHECK_VALID(NULL);
  162.     if (!PyArg_ParseTuple (args, "l", &num_bytes))
  163.         return(NULL);
  164.  
  165.     /* silently 'adjust' out-of-range requests */
  166.     if ((self->pos + num_bytes) > self->size) {
  167.         num_bytes -= (self->pos+num_bytes) - self->size;
  168.     }
  169.     result = Py_BuildValue("s#", self->data+self->pos, num_bytes);
  170.     self->pos += num_bytes;     
  171.     return (result);
  172. }
  173.  
  174. static PyObject *
  175. mmap_find_method (mmap_object *self,
  176.               PyObject *args)
  177. {
  178.     long start = self->pos;
  179.     char * needle;
  180.     int len;
  181.  
  182.     CHECK_VALID(NULL);
  183.     if (!PyArg_ParseTuple (args, "s#|l", &needle, &len, &start)) {
  184.         return NULL;
  185.     } else {
  186.         char * p = self->data+self->pos;
  187.         char * e = self->data+self->size;
  188.         while (p < e) {
  189.             char * s = p;
  190.             char * n = needle;
  191.             while ((s<e) && (*n) && !(*s-*n)) {
  192.                 s++, n++;
  193.             }
  194.             if (!*n) {
  195.                 return Py_BuildValue (
  196.                     "l",
  197.                     (long) (p - (self->data + start)));
  198.             }
  199.             p++;
  200.         }
  201.         return Py_BuildValue ("l", (long) -1);
  202.     }
  203. }
  204.  
  205. static PyObject *
  206. mmap_write_method (mmap_object * self,
  207.                PyObject * args)
  208. {
  209.     long length;
  210.     char * data;
  211.  
  212.     CHECK_VALID(NULL);
  213.     if (!PyArg_ParseTuple (args, "s#", &data, &length))
  214.         return(NULL);
  215.  
  216.     if ((self->pos + length) > self->size) {
  217.         PyErr_SetString (PyExc_ValueError, "data out of range");
  218.         return NULL;
  219.     }
  220.     memcpy (self->data+self->pos, data, length);
  221.     self->pos = self->pos+length;
  222.     Py_INCREF (Py_None);
  223.     return (Py_None);
  224. }
  225.  
  226. static PyObject *
  227. mmap_write_byte_method (mmap_object * self,
  228.                 PyObject * args)
  229. {
  230.     char value;
  231.  
  232.     CHECK_VALID(NULL);
  233.     if (!PyArg_ParseTuple (args, "c", &value))
  234.         return(NULL);
  235.  
  236.     *(self->data+self->pos) = value;
  237.     self->pos += 1;
  238.     Py_INCREF (Py_None);
  239.     return (Py_None);
  240. }
  241.  
  242. static PyObject *
  243. mmap_size_method (mmap_object * self,
  244.               PyObject * args)
  245. {
  246.     CHECK_VALID(NULL);
  247.  
  248. #ifdef MS_WIN32
  249.     if (self->file_handle != (HFILE) 0xFFFFFFFF) {
  250.         return (Py_BuildValue (
  251.             "l",
  252.             GetFileSize ((HANDLE)self->file_handle, NULL)));
  253.     } else {
  254.         return (Py_BuildValue ("l", self->size) );
  255.     }
  256. #endif /* MS_WIN32 */
  257.  
  258. #ifdef UNIX
  259.     return (Py_BuildValue ("l", self->size) );
  260. #endif /* UNIX */
  261. }
  262.  
  263. /* This assumes that you want the entire file mapped,
  264.  / and when recreating the map will make the new file
  265.  / have the new size
  266.  /
  267.  / Is this really necessary?  This could easily be done
  268.  / from python by just closing and re-opening with the
  269.  / new size?
  270.  */
  271.  
  272. static PyObject *
  273. mmap_resize_method (mmap_object * self,
  274.             PyObject * args)
  275. {
  276.     unsigned long new_size;
  277.     CHECK_VALID(NULL);
  278.     if (!PyArg_ParseTuple (args, "l", &new_size)) {
  279.         return NULL;
  280. #ifdef MS_WIN32
  281.     } else { 
  282.         DWORD dwErrCode = 0;
  283.         /* First, unmap the file view */
  284.         UnmapViewOfFile (self->data);
  285.         /* Close the mapping object */
  286.         CloseHandle ((HANDLE)self->map_handle);
  287.         /* Move to the desired EOF position */
  288.         SetFilePointer ((HANDLE)self->file_handle,
  289.                 new_size, NULL, FILE_BEGIN);
  290.         /* Change the size of the file */
  291.         SetEndOfFile ((HANDLE)self->file_handle);
  292.         /* Create another mapping object and remap the file view */
  293.         self->map_handle = CreateFileMapping (
  294.             (HANDLE) self->file_handle,
  295.             NULL,
  296.             PAGE_READWRITE,
  297.             0,
  298.             new_size,
  299.             self->tagname);
  300.         if (self->map_handle != NULL) {
  301.             self->data = (char *) MapViewOfFile (self->map_handle,
  302.                                  FILE_MAP_WRITE,
  303.                                  0,
  304.                                  0,
  305.                                  0);
  306.             if (self->data != NULL) {
  307.                 self->size = new_size;
  308.                 Py_INCREF (Py_None);
  309.                 return Py_None;
  310.             } else {
  311.                 dwErrCode = GetLastError();
  312.             }
  313.         } else {
  314.             dwErrCode = GetLastError();
  315.         }
  316.         PyErr_SetFromWindowsErr(dwErrCode);
  317.         return (NULL);
  318. #endif /* MS_WIN32 */
  319.  
  320. #ifdef UNIX
  321. #ifndef MREMAP_MAYMOVE
  322. } else {
  323.     PyErr_SetString(PyExc_SystemError,
  324.             "mmap: resizing not available--no mremap()");
  325.     return NULL;
  326. #else
  327. } else {
  328.     void *newmap;
  329.  
  330.     newmap = mremap(self->data, self->size, new_size, MREMAP_MAYMOVE);
  331.     if (newmap == (void *)-1) 
  332.     {
  333.         PyErr_SetFromErrno(mmap_module_error);
  334.         return NULL;
  335.     }
  336.     self->data = newmap;
  337.     self->size = new_size;
  338.     Py_INCREF(Py_None);
  339.     return Py_None;
  340. #endif /* MREMAP_MAYMOVE */
  341. #endif /* UNIX */
  342. }
  343. }
  344.  
  345. static PyObject *
  346. mmap_tell_method (mmap_object * self, PyObject * args)
  347. {
  348.     CHECK_VALID(NULL);
  349.     return (Py_BuildValue ("l", self->pos) );
  350. }
  351.  
  352. static PyObject *
  353. mmap_flush_method (mmap_object * self, PyObject * args)
  354. {
  355.     size_t offset    = 0;
  356.     size_t size = self->size;
  357.     CHECK_VALID(NULL);
  358.     if (!PyArg_ParseTuple (args, "|ll", &offset, &size)) {
  359.         return NULL;
  360.     } else if ((offset + size) > self->size) {
  361.         PyErr_SetString (PyExc_ValueError,
  362.                  "flush values out of range");
  363.         return NULL;
  364.     } else {
  365. #ifdef MS_WIN32
  366.         return (Py_BuildValue (
  367.             "l", FlushViewOfFile (self->data+offset, size)));
  368. #endif /* MS_WIN32 */
  369. #ifdef UNIX
  370.         /* XXX semantics of return value? */
  371.         /* XXX flags for msync? */
  372.         if (-1 == msync(self->data + offset, size,
  373.                 MS_SYNC | MS_INVALIDATE))
  374.         {
  375.             PyErr_SetFromErrno(mmap_module_error);
  376.             return NULL;
  377.         }
  378.         return Py_BuildValue ("l", 0);    
  379. #endif /* UNIX */   
  380.     }
  381. }
  382.  
  383. static PyObject *
  384. mmap_seek_method (mmap_object * self, PyObject * args)
  385. {
  386.     /* ptrdiff_t dist; */
  387.     long dist;
  388.     int how=0;
  389.     CHECK_VALID(NULL);
  390.     if (!PyArg_ParseTuple (args, "l|i", &dist, &how)) {
  391.         return(NULL);
  392.     } else {
  393.         unsigned long where;
  394.         switch (how) {
  395.         case 0:
  396.             where = dist;
  397.             break;
  398.         case 1:
  399.             where = self->pos + dist;
  400.             break;
  401.         case 2:
  402.             where = self->size - dist;
  403.             break;
  404.         default:
  405.             PyErr_SetString (PyExc_ValueError,
  406.                      "unknown seek type");
  407.             return NULL;
  408.         }
  409.         if ((where >= 0) && (where < (self->size))) {
  410.             self->pos = where;
  411.             Py_INCREF (Py_None);
  412.             return (Py_None);
  413.         } else {
  414.             PyErr_SetString (PyExc_ValueError,
  415.                      "seek out of range");
  416.             return NULL;
  417.         }
  418.     }
  419. }
  420.  
  421. static PyObject *
  422. mmap_move_method (mmap_object * self, PyObject * args)
  423. {
  424.     unsigned long dest, src, count;
  425.     CHECK_VALID(NULL);
  426.     if (!PyArg_ParseTuple (args, "iii", &dest, &src, &count)) {
  427.         return NULL;
  428.     } else {
  429.         /* bounds check the values */
  430.         if (/* end of source after end of data?? */
  431.             ((src+count) > self->size)
  432.             /* dest will fit? */
  433.             || (dest+count > self->size)) {
  434.             PyErr_SetString (PyExc_ValueError,
  435.                      "source or destination out of range");
  436.             return NULL;
  437.         } else {
  438.             memmove (self->data+dest, self->data+src, count);
  439.             Py_INCREF (Py_None);
  440.             return Py_None;
  441.         }
  442.     }
  443. }
  444.  
  445. static struct PyMethodDef mmap_object_methods[] = {
  446.     {"close",    (PyCFunction) mmap_close_method,    1},
  447.     {"find",    (PyCFunction) mmap_find_method,        1},
  448.     {"flush",    (PyCFunction) mmap_flush_method,    1},
  449.     {"move",    (PyCFunction) mmap_move_method,        1},
  450.     {"read",    (PyCFunction) mmap_read_method,        1},
  451.     {"read_byte",    (PyCFunction) mmap_read_byte_method,      1},
  452.     {"readline",    (PyCFunction) mmap_read_line_method,    1},
  453.     {"resize",    (PyCFunction) mmap_resize_method,    1},
  454.     {"seek",    (PyCFunction) mmap_seek_method,        1},
  455.     {"size",    (PyCFunction) mmap_size_method,        1},
  456.     {"tell",    (PyCFunction) mmap_tell_method,        1},
  457.     {"write",    (PyCFunction) mmap_write_method,    1},
  458.     {"write_byte",    (PyCFunction) mmap_write_byte_method,    1},
  459.     {NULL,       NULL}       /* sentinel */
  460. };
  461.  
  462. /* Functions for treating an mmap'ed file as a buffer */
  463.  
  464. static int
  465. mmap_buffer_getreadbuf(self, index, ptr)
  466.     mmap_object *self;
  467. int index;
  468. const void **ptr;
  469. {
  470.     CHECK_VALID(-1);
  471.     if ( index != 0 ) {
  472.         PyErr_SetString(PyExc_SystemError,
  473.                 "Accessing non-existent mmap segment");
  474.         return -1;
  475.     }
  476.     *ptr = self->data;
  477.     return self->size;
  478. }
  479.  
  480. static int
  481. mmap_buffer_getwritebuf(self, index, ptr)
  482.     mmap_object *self;
  483.     int index;
  484.     const void **ptr;
  485. {  
  486.     CHECK_VALID(-1);
  487.     if ( index != 0 ) {
  488.         PyErr_SetString(PyExc_SystemError,
  489.                 "Accessing non-existent mmap segment");
  490.         return -1;
  491.     }
  492.     *ptr = self->data;
  493.     return self->size;
  494. }
  495.  
  496. static int
  497. mmap_buffer_getsegcount(self, lenp)
  498.     mmap_object *self;
  499.     int *lenp;
  500. {
  501.     CHECK_VALID(-1);
  502.     if (lenp) 
  503.         *lenp = self->size;
  504.     return 1;
  505. }
  506.  
  507. static int
  508. mmap_buffer_getcharbuffer(self, index, ptr)
  509.     mmap_object *self;
  510.     int index;
  511.     const void **ptr;
  512. {
  513.     if ( index != 0 ) {
  514.         PyErr_SetString(PyExc_SystemError,
  515.                 "accessing non-existent buffer segment");
  516.         return -1;
  517.     }
  518.     *ptr = (const char *)self->data;
  519.     return self->size;
  520. }
  521.  
  522. static PyObject *
  523. mmap_object_getattr(mmap_object * self, char * name)
  524. {
  525.     return Py_FindMethod (mmap_object_methods, (PyObject *)self, name);
  526. }
  527.  
  528. static int
  529. mmap_length(self)
  530.     mmap_object *self;
  531. {
  532.     CHECK_VALID(-1);
  533.     return self->size;
  534. }
  535.  
  536. static PyObject *
  537. mmap_item(self, i)
  538.     mmap_object *self;
  539.     int i;
  540. {
  541.     CHECK_VALID(NULL);
  542.     if (i < 0 || i >= self->size) {
  543.         PyErr_SetString(PyExc_IndexError, "mmap index out of range");
  544.         return NULL;
  545.     }
  546.     return PyString_FromStringAndSize(self->data + i, 1);
  547. }
  548.  
  549. static PyObject *
  550. mmap_slice(self, ilow, ihigh)
  551.     mmap_object *self;
  552.     int ilow, ihigh;
  553. {
  554.     CHECK_VALID(NULL);
  555.     if (ilow < 0)
  556.         ilow = 0;
  557.     else if (ilow > self->size)
  558.         ilow = self->size;
  559.     if (ihigh < 0)
  560.         ihigh = 0;
  561.     if (ihigh < ilow)
  562.         ihigh = ilow;
  563.     else if (ihigh > self->size)
  564.         ihigh = self->size;
  565.     
  566.     return PyString_FromStringAndSize(self->data + ilow, ihigh-ilow);
  567. }
  568.  
  569. static PyObject *
  570. mmap_concat(self, bb)
  571.     mmap_object *self;
  572.     PyObject *bb;
  573. {
  574.     CHECK_VALID(NULL);
  575.     PyErr_SetString(PyExc_SystemError,
  576.             "mmaps don't support concatenation");
  577.     return NULL;
  578. }
  579.  
  580. static PyObject *
  581. mmap_repeat(self, n)
  582.     mmap_object *self;
  583.     int n;
  584. {
  585.     CHECK_VALID(NULL);
  586.     PyErr_SetString(PyExc_SystemError,
  587.             "mmaps don't support repeat operation");
  588.     return NULL;
  589. }
  590.  
  591. static int
  592. mmap_ass_slice(self, ilow, ihigh, v)
  593.     mmap_object *self;
  594.     int ilow, ihigh;
  595.     PyObject *v;
  596. {
  597.     const char *buf;
  598.  
  599.     CHECK_VALID(-1);
  600.     if (ilow < 0)
  601.         ilow = 0;
  602.     else if (ilow > self->size)
  603.         ilow = self->size;
  604.     if (ihigh < 0)
  605.         ihigh = 0;
  606.     if (ihigh < ilow)
  607.         ihigh = ilow;
  608.     else if (ihigh > self->size)
  609.         ihigh = self->size;
  610.     
  611.     if (! (PyString_Check(v)) ) {
  612.         PyErr_SetString(PyExc_IndexError, 
  613.                 "mmap slice assignment must be a string");
  614.         return -1;
  615.     }
  616.     if ( PyString_Size(v) != (ihigh - ilow) ) {
  617.         PyErr_SetString(PyExc_IndexError, 
  618.                 "mmap slice assignment is wrong size");
  619.         return -1;
  620.     }
  621.     buf = PyString_AsString(v);
  622.     memcpy(self->data + ilow, buf, ihigh-ilow);
  623.     return 0;
  624. }
  625.  
  626. static int
  627. mmap_ass_item(self, i, v)
  628.     mmap_object *self;
  629.     int i;
  630.     PyObject *v;
  631. {
  632.     const char *buf;
  633.  
  634.     CHECK_VALID(-1);
  635.     if (i < 0 || i >= self->size) {
  636.         PyErr_SetString(PyExc_IndexError, "mmap index out of range");
  637.         return -1;
  638.     }
  639.     if (! (PyString_Check(v) && PyString_Size(v)==1) ) {
  640.         PyErr_SetString(PyExc_IndexError, 
  641.             "mmap assignment must be single-character string");
  642.         return -1;
  643.     }
  644.     buf = PyString_AsString(v);
  645.     self->data[i] = buf[0];
  646.     return 0;
  647. }
  648.  
  649. static PySequenceMethods mmap_as_sequence = {
  650.     (inquiry)mmap_length,               /*sq_length*/
  651.     (binaryfunc)mmap_concat,           /*sq_concat*/
  652.     (intargfunc)mmap_repeat,           /*sq_repeat*/
  653.     (intargfunc)mmap_item,               /*sq_item*/
  654.     (intintargfunc)mmap_slice,           /*sq_slice*/
  655.     (intobjargproc)mmap_ass_item,           /*sq_ass_item*/
  656.     (intintobjargproc)mmap_ass_slice,      /*sq_ass_slice*/
  657. };
  658.  
  659. static PyBufferProcs mmap_as_buffer = {
  660.     (getreadbufferproc)mmap_buffer_getreadbuf,
  661.     (getwritebufferproc)mmap_buffer_getwritebuf,
  662.     (getsegcountproc)mmap_buffer_getsegcount,
  663.     (getcharbufferproc)mmap_buffer_getcharbuffer,
  664. };
  665.  
  666. static PyTypeObject mmap_object_type = {
  667.     PyObject_HEAD_INIT(0) /* patched in module init */
  668.     0,                    /* ob_size */
  669.     "mmap",                    /* tp_name */
  670.     sizeof(mmap_object),            /* tp_size */
  671.     0,                    /* tp_itemsize */
  672.     /* methods */
  673.     (destructor) mmap_object_dealloc,    /* tp_dealloc */
  674.     0,                    /* tp_print */
  675.     (getattrfunc) mmap_object_getattr,    /* tp_getattr */
  676.     0,                    /* tp_setattr */
  677.     0,                    /* tp_compare */
  678.     0,                    /* tp_repr */
  679.     0,                    /* tp_as_number */
  680.     &mmap_as_sequence,            /*tp_as_sequence*/
  681.     0,                    /*tp_as_mapping*/
  682.     0,                    /*tp_hash*/
  683.     0,                    /*tp_call*/
  684.     0,                    /*tp_str*/
  685.     0,                    /*tp_getattro*/
  686.     0,                    /*tp_setattro*/
  687.     &mmap_as_buffer,            /*tp_as_buffer*/
  688.     Py_TPFLAGS_HAVE_GETCHARBUFFER,        /*tp_flags*/
  689.     0,                    /*tp_doc*/
  690. };
  691.  
  692. #ifdef UNIX 
  693. static PyObject *
  694. new_mmap_object (PyObject * self, PyObject * args, PyObject *kwdict)
  695. {
  696.     mmap_object * m_obj;
  697.     unsigned long map_size;
  698.     int fd, flags = MAP_SHARED, prot = PROT_WRITE | PROT_READ;
  699.     char * filename;
  700.     int namelen;
  701.     char *keywords[] = {"file", "size", "flags", "prot", NULL};
  702.  
  703.     if (!PyArg_ParseTupleAndKeywords(args, kwdict, 
  704.                      "il|ii", keywords, 
  705.                      &fd, &map_size, &flags, &prot)
  706.         )
  707.         return NULL;
  708.   
  709.     m_obj = PyObject_New (mmap_object, &mmap_object_type);
  710.     if (m_obj == NULL) {return NULL;}
  711.     m_obj->size = (size_t) map_size;
  712.     m_obj->pos = (size_t) 0;
  713.     m_obj->data = mmap(NULL, map_size, 
  714.                prot, flags,
  715.                fd, 0);
  716.     if (m_obj->data == (void *)-1)
  717.     {
  718.         Py_DECREF(m_obj);
  719.         PyErr_SetFromErrno(mmap_module_error);
  720.         return NULL;
  721.     }
  722.     return (PyObject *)m_obj;
  723. }
  724. #endif /* UNIX */
  725.  
  726. #ifdef MS_WIN32
  727. static PyObject *
  728. new_mmap_object (PyObject * self, PyObject * args)
  729. {
  730.     mmap_object * m_obj;
  731.     unsigned long map_size;
  732.     char * tagname = "";
  733.  
  734.     DWORD dwErr = 0;
  735.     int fileno;
  736.     HFILE fh = 0;
  737.  
  738.     /* Patch the object type */
  739.     mmap_object_type.ob_type = &PyType_Type;
  740.  
  741.     if (!PyArg_ParseTuple(args,
  742.               "il|z",
  743.               &fileno,
  744.               &map_size,
  745.               &tagname)
  746.         )
  747.         return NULL;
  748.   
  749.     /* if an actual filename has been specified */
  750.     if (fileno != 0) {
  751.         fh = _get_osfhandle(fileno);
  752.         if (fh==-1) {
  753.             PyErr_SetFromErrno(mmap_module_error);
  754.             return NULL;
  755.         }
  756.         /* Win9x appears to need us seeked to zero */
  757.         fseek(&_iob[fileno], 0, SEEK_SET);
  758.     }
  759.  
  760.     m_obj = PyObject_New (mmap_object, &mmap_object_type);
  761.     
  762.     if (fh) {
  763.         m_obj->file_handle = fh;
  764.         if (!map_size) {
  765.             m_obj->size = GetFileSize ((HANDLE)fh, NULL);
  766.         } else {
  767.             m_obj->size = map_size;
  768.         }
  769.     }
  770.     else {
  771.         m_obj->file_handle = (HFILE) 0xFFFFFFFF;
  772.         m_obj->size = map_size;
  773.     }
  774.  
  775.     /* set the initial position */
  776.     m_obj->pos = (size_t) 0;
  777.  
  778.     m_obj->map_handle = CreateFileMapping ((HANDLE) m_obj->file_handle,
  779.                            NULL,
  780.                            PAGE_READWRITE,
  781.                            0,
  782.                            m_obj->size,
  783.                            tagname);
  784.     if (m_obj->map_handle != NULL) {
  785.         m_obj->data = (char *) MapViewOfFile (m_obj->map_handle,
  786.                               FILE_MAP_WRITE,
  787.                               0,
  788.                               0,
  789.                               0);
  790.         if (m_obj->data != NULL) {
  791.             return ((PyObject *) m_obj);
  792.         } else {
  793.             dwErr = GetLastError();
  794.         }
  795.     } else {
  796.         dwErr = GetLastError();
  797.     }
  798.     PyErr_SetFromWindowsErr(dwErr);
  799.     return (NULL);
  800. }
  801. #endif /* MS_WIN32 */
  802.  
  803. /* List of functions exported by this module */
  804. static struct PyMethodDef mmap_functions[] = {
  805.     {"mmap",    (PyCFunction) new_mmap_object, 
  806.      METH_VARARGS|METH_KEYWORDS},
  807.     {NULL,        NULL}         /* Sentinel */
  808. };
  809.  
  810. #ifdef MS_WIN32
  811. __declspec(dllexport) void
  812. #endif /* MS_WIN32 */
  813. #ifdef UNIX
  814. extern void
  815. #endif
  816.  
  817. initmmap(void)
  818. {
  819.     PyObject *dict, *module;
  820.     module = Py_InitModule ("mmap", mmap_functions);
  821.     dict = PyModule_GetDict (module);
  822.     mmap_module_error = PyExc_EnvironmentError;
  823.     Py_INCREF(mmap_module_error);
  824.     PyDict_SetItemString (dict, "error", mmap_module_error);
  825. #ifdef PROT_EXEC
  826.     PyDict_SetItemString (dict, "PROT_EXEC", PyInt_FromLong(PROT_EXEC) );
  827. #endif
  828. #ifdef PROT_READ
  829.     PyDict_SetItemString (dict, "PROT_READ", PyInt_FromLong(PROT_READ) );
  830. #endif
  831. #ifdef PROT_WRITE
  832.     PyDict_SetItemString (dict, "PROT_WRITE", PyInt_FromLong(PROT_WRITE) );
  833. #endif
  834.  
  835. #ifdef MAP_SHARED
  836.     PyDict_SetItemString (dict, "MAP_SHARED", PyInt_FromLong(MAP_SHARED) );
  837. #endif
  838. #ifdef MAP_PRIVATE
  839.     PyDict_SetItemString (dict, "MAP_PRIVATE",
  840.                   PyInt_FromLong(MAP_PRIVATE) );
  841. #endif
  842. #ifdef MAP_DENYWRITE
  843.     PyDict_SetItemString (dict, "MAP_DENYWRITE",
  844.                   PyInt_FromLong(MAP_DENYWRITE) );
  845. #endif
  846. #ifdef MAP_EXECUTABLE
  847.     PyDict_SetItemString (dict, "MAP_EXECUTABLE",
  848.                   PyInt_FromLong(MAP_EXECUTABLE) );
  849. #endif
  850. #ifdef MAP_ANON
  851.     PyDict_SetItemString (dict, "MAP_ANON", PyInt_FromLong(MAP_ANON) );
  852.     PyDict_SetItemString (dict, "MAP_ANONYMOUS",
  853.                   PyInt_FromLong(MAP_ANON) );
  854. #endif
  855.  
  856. #ifdef UNIX
  857.     PyDict_SetItemString (dict, "PAGESIZE",
  858.                   PyInt_FromLong( (long)getpagesize() ) );
  859. #endif
  860. #ifdef MS_WIN32
  861.     {
  862.         SYSTEM_INFO si;
  863.         GetSystemInfo(&si);
  864.         PyDict_SetItemString (dict, "PAGESIZE",
  865.                   PyInt_FromLong( si.dwPageSize ) );
  866.     }
  867. #endif /* MS_WIN32 */
  868.  
  869. }
  870.